home *** CD-ROM | disk | FTP | other *** search
/ 17 Bit Software 6: Level 6 / 17 Bit - Level 6 (1998)(Epic Marketing)[!].iso / quartz / q0429.dms / q0429.adf / libray / libcommon / transform.c < prev    next >
C/C++ Source or Header  |  1992-05-20  |  11KB  |  438 lines

  1. /*
  2.  * transform.c
  3.  *
  4.  * Copyright (C) 1989, 1991, Craig E. Kolb
  5.  * All rights reserved.
  6.  *
  7.  * This software may be freely copied, modified, and redistributed
  8.  * provided that this copyright notice is preserved on all copies.
  9.  *
  10.  * You may not distribute this software, in whole or in part, as part of
  11.  * any commercial product without the express consent of the authors.
  12.  *
  13.  * There is no warranty or other guarantee of fitness of this software
  14.  * for any purpose.  It is provided solely "as is".
  15.  *
  16.  * $Id: transform.c,v 4.0.1.1 91/09/29 15:37:06 cek Exp Locker: cek $
  17.  *
  18.  * $Log:    transform.c,v $
  19.  * Revision 4.0.1.1  91/09/29  15:37:06  cek
  20.  * patch1: CoordSysTransform did not detect up-Z == -1.
  21.  * 
  22.  * Revision 4.0  91/07/17  14:32:25  kolb
  23.  * Initial version.
  24.  * 
  25.  */
  26. #include "common.h"
  27.  
  28. /*
  29.  * Matrices are indexed row-first; that is:
  30.  * matrix[ROW][COLUMN]
  31.  */
  32. /*
  33.  * Allocate new structure that holds both object-to-world and
  34.  * world-to-object space transformation structures.  It probably
  35.  * should hold pointers to these structures.
  36.  */
  37. Trans *
  38. TransCreate(tr, meth)
  39. TransRef tr;
  40. TransMethods *meth;
  41. {
  42.     Trans *res;
  43.  
  44.     res = (Trans *)share_malloc(sizeof(Trans));
  45.     res->tr = tr;
  46.     res->methods = meth;
  47.     res->animated = FALSE;
  48.     res->assoc = (ExprAssoc *)NULL;
  49.     res->prev = res->next = (Trans *)NULL;
  50.     MatrixInit(&res->trans);
  51.     MatrixInit(&res->itrans);
  52.     return res;
  53. }
  54.  
  55. void
  56. TransFree(trans)
  57. Trans *trans;
  58. {
  59.     if (trans->tr)
  60.         free((voidstar)trans->tr);
  61.     free((voidstar)trans);
  62. }
  63.  
  64. void
  65. TransAssoc(trans, ptr, expr)
  66. Trans *trans;
  67. Float *ptr;
  68. Expr *expr;
  69. {
  70.     ExprAssoc *assoc;
  71.  
  72.     if (expr->timevary) {
  73.         /*
  74.          * Gotta store the sucker.
  75.          */
  76.         trans->assoc = AssocCreate(ptr, expr, trans->assoc);
  77.         trans->animated = TRUE;
  78.     } else {
  79.         *ptr = expr->value;
  80.     }
  81.     fflush(stderr);
  82. }
  83.  
  84. /*
  85.  * Allocate new transformation 'matrix'.
  86.  */
  87. RSMatrix *
  88. MatrixCreate()
  89. {
  90.     RSMatrix *res;
  91.  
  92.     res = (RSMatrix *)share_malloc(sizeof(RSMatrix));
  93.     MatrixInit(res);
  94.     return res;
  95. }
  96.  
  97. /*
  98.  * Multiply m1 and m2, copy result into "res".
  99.  */
  100. void
  101. MatrixMult(t1, t2, res)
  102. RSMatrix *t1, *t2, *res;
  103. {
  104.     register int i;
  105.     RSMatrix tmp;
  106.  
  107.     for (i = 0; i < 3; i++) {
  108.         tmp.matrix[i][0] = t1->matrix[i][0] * t2->matrix[0][0] +
  109.                      t1->matrix[i][1] * t2->matrix[1][0] +
  110.                      t1->matrix[i][2] * t2->matrix[2][0];
  111.         tmp.matrix[i][1] = t1->matrix[i][0] * t2->matrix[0][1] +
  112.                      t1->matrix[i][1] * t2->matrix[1][1] +
  113.                      t1->matrix[i][2] * t2->matrix[2][1];
  114.         tmp.matrix[i][2] = t1->matrix[i][0] * t2->matrix[0][2] +
  115.                      t1->matrix[i][1] * t2->matrix[1][2] +
  116.                      t1->matrix[i][2] * t2->matrix[2][2];
  117.     }
  118.  
  119.     tmp.translate.x = t1->translate.x * t2->matrix[0][0] +
  120.               t1->translate.y * t2->matrix[1][0] +
  121.               t1->translate.z * t2->matrix[2][0] + t2->translate.x;
  122.     tmp.translate.y = t1->translate.x * t2->matrix[0][1] +
  123.               t1->translate.y * t2->matrix[1][1] +
  124.               t1->translate.z * t2->matrix[2][1] + t2->translate.y;
  125.     tmp.translate.z = t1->translate.x * t2->matrix[0][2] +
  126.               t1->translate.y * t2->matrix[1][2] +
  127.               t1->translate.z * t2->matrix[2][2] + t2->translate.z;
  128.     MatrixCopy(&tmp, res);
  129. }
  130.  
  131. /*
  132.  * Return transformation information to map the "coordinate system"
  133.  * with the given origin, "up" vector, radius, and up axis lengths to
  134.  * one in which the "up" vector is the Z axis and the x/y/up axes
  135.  * have unit length.  This is useful for transforming a general
  136.  * form of a primitive into a canonical, Z-axis aligned, unit size
  137.  * primitive, facilitating intersection testing.
  138.  * Assumes that "up" is normalized.
  139.  */
  140. void
  141. CoordSysTransform(origin, up, r, len, trans)
  142. Vector *origin, *up;
  143. Float r, len;
  144. Trans *trans;
  145. {
  146.     RSMatrix tmp;
  147.     Vector atmp;
  148.  
  149.     ScaleMatrix(r, r, len, &trans->trans);
  150.     if (1. - fabs(up->z) < EPSILON) {
  151.         atmp.x = 1.;
  152.         atmp.y = atmp.z = 0.;
  153.     } else {
  154.         atmp.x = up->y;
  155.         atmp.y = -up->x;
  156.         atmp.z= 0.;
  157.     }
  158.     /*
  159.      * Might want to make sure that |up->z| is < 1.
  160.      */
  161.     RotationMatrix(atmp.x, atmp.y, atmp.z, -acos(up->z), &tmp);
  162.     MatrixMult(&trans->trans, &tmp, &trans->trans);
  163.     TranslationMatrix(origin->x, origin->y, origin->z, &tmp);
  164.     MatrixMult(&trans->trans, &tmp, &trans->trans);
  165.     MatrixInvert(&trans->trans, &trans->itrans);
  166. }
  167.  
  168. void
  169. TransCopy(from, into)
  170. Trans *into, *from;
  171. {
  172.     MatrixCopy(&from->trans, &into->trans);
  173.     MatrixCopy(&from->itrans, &into->itrans);
  174. }
  175.  
  176. void
  177. TransInvert(from, into)
  178. Trans *into, *from;
  179. {
  180.     RSMatrix ttmp;
  181.     /*
  182.      * In case into == from...
  183.      */
  184.     if (from == into) {
  185.         ttmp = from->trans;
  186.         into->trans = from->itrans;
  187.         into->itrans = ttmp;
  188.     } else {
  189.         into->trans = from->itrans;
  190.         into->itrans = from->trans;
  191.     }
  192. }
  193.  
  194. /*
  195.  * Copy a given transformation structure.
  196.  */
  197. void
  198. MatrixCopy(from, into)
  199. RSMatrix *into, *from;
  200. {
  201.     into->matrix[0][0] = from->matrix[0][0];
  202.     into->matrix[0][1] = from->matrix[0][1];
  203.     into->matrix[0][2] = from->matrix[0][2];
  204.     into->matrix[1][0] = from->matrix[1][0];
  205.     into->matrix[1][1] = from->matrix[1][1];
  206.     into->matrix[1][2] = from->matrix[1][2];
  207.     into->matrix[2][0] = from->matrix[2][0];
  208.     into->matrix[2][1] = from->matrix[2][1];
  209.     into->matrix[2][2] = from->matrix[2][2];
  210.     into->translate = from->translate;
  211. }
  212.  
  213. void
  214. TransInit(trans)
  215. Trans *trans;
  216. {
  217.     MatrixInit(&trans->trans);
  218.     MatrixInit(&trans->itrans);
  219. }
  220.  
  221. void
  222. TransCompose(t1, t2, res)
  223. Trans *t1, *t2, *res;
  224. {
  225.     MatrixMult(&t1->trans, &t2->trans, &res->trans);
  226.     MatrixMult(&t2->itrans, &t1->itrans, &res->itrans);
  227. }
  228.  
  229. /*
  230.  * Initialize transformation structure.
  231.  */
  232. void
  233. MatrixInit(trans)
  234. RSMatrix *trans;
  235. {
  236.     trans->matrix[0][0] = trans->matrix[1][1] = trans->matrix[2][2] = 1.;
  237.     trans->matrix[0][1] = trans->matrix[0][2] = trans->matrix[1][0] =
  238.     trans->matrix[1][2] = trans->matrix[2][0] = trans->matrix[2][1] = 0.;
  239.     trans->translate.x = trans->translate.y = trans->translate.z = 0.;
  240. }
  241.  
  242. /*
  243.  * Calculate inverse of the given transformation structure.
  244.  */
  245. void
  246. MatrixInvert(trans, inverse)
  247. RSMatrix *inverse, *trans;
  248. {
  249.     RSMatrix ttmp;
  250.     int i;
  251.     Float d;
  252.     extern int yylineno;
  253.  
  254.     ttmp.matrix[0][0] = trans->matrix[1][1]*trans->matrix[2][2] -
  255.                 trans->matrix[1][2]*trans->matrix[2][1];
  256.     ttmp.matrix[1][0] = trans->matrix[1][0]*trans->matrix[2][2] -
  257.                 trans->matrix[1][2]*trans->matrix[2][0];
  258.     ttmp.matrix[2][0] = trans->matrix[1][0]*trans->matrix[2][1] -
  259.                 trans->matrix[1][1]*trans->matrix[2][0];
  260.  
  261.     ttmp.matrix[0][1] = trans->matrix[0][1]*trans->matrix[2][2] -
  262.                 trans->matrix[0][2]*trans->matrix[2][1];
  263.     ttmp.matrix[1][1] = trans->matrix[0][0]*trans->matrix[2][2] -
  264.                 trans->matrix[0][2]*trans->matrix[2][0];
  265.     ttmp.matrix[2][1] = trans->matrix[0][0]*trans->matrix[2][1] -
  266.                 trans->matrix[0][1]*trans->matrix[2][0];
  267.  
  268.     ttmp.matrix[0][2] = trans->matrix[0][1]*trans->matrix[1][2] -
  269.                 trans->matrix[0][2]*trans->matrix[1][1];
  270.     ttmp.matrix[1][2] = trans->matrix[0][0]*trans->matrix[1][2] -
  271.                 trans->matrix[0][2]*trans->matrix[1][0];
  272.     ttmp.matrix[2][2] = trans->matrix[0][0]*trans->matrix[1][1] -
  273.                 trans->matrix[0][1]*trans->matrix[1][0];
  274.  
  275.     d = trans->matrix[0][0]*ttmp.matrix[0][0] -
  276.         trans->matrix[0][1]*ttmp.matrix[1][0] +
  277.         trans->matrix[0][2]*ttmp.matrix[2][0];
  278.  
  279.     if (fabs(d) < EPSILON*EPSILON)
  280.         RLerror(RL_PANIC, "Singular matrix.\n",yylineno);
  281.  
  282.     ttmp.matrix[0][0] /= d;
  283.     ttmp.matrix[0][2] /= d;
  284.     ttmp.matrix[1][1] /= d;
  285.     ttmp.matrix[2][0] /= d;
  286.     ttmp.matrix[2][2] /= d;
  287.  
  288.     d = -d;
  289.  
  290.     ttmp.matrix[0][1] /= d;
  291.     ttmp.matrix[1][0] /= d;
  292.     ttmp.matrix[1][2] /= d;
  293.     ttmp.matrix[2][1] /= d;
  294.  
  295.     ttmp.translate.x = -(ttmp.matrix[0][0]*trans->translate.x +
  296.                  ttmp.matrix[1][0]*trans->translate.y +
  297.                  ttmp.matrix[2][0]*trans->translate.z);
  298.     ttmp.translate.y = -(ttmp.matrix[0][1]*trans->translate.x +
  299.                  ttmp.matrix[1][1]*trans->translate.y +
  300.                  ttmp.matrix[2][1]*trans->translate.z);
  301.     ttmp.translate.z = -(ttmp.matrix[0][2]*trans->translate.x +
  302.                  ttmp.matrix[1][2]*trans->translate.y +
  303.                  ttmp.matrix[2][2]*trans->translate.z);
  304.  
  305.     MatrixCopy(&ttmp, inverse);
  306. }
  307.  
  308. /*
  309.  * Apply a transformation to a point (translation affects the point).
  310.  */
  311. void
  312. PointTransform(vec, trans)
  313. Vector *vec;
  314. RSMatrix *trans;
  315. {
  316.     Vector tmp;
  317.  
  318.     tmp.x = vec->x * trans->matrix[0][0] + vec->y * trans->matrix[1][0] +
  319.             vec->z * trans->matrix[2][0] + trans->translate.x;
  320.     tmp.y = vec->x * trans->matrix[0][1] + vec->y * trans->matrix[1][1] +
  321.             vec->z * trans->matrix[2][1] + trans->translate.y;
  322.     tmp.z = vec->x * trans->matrix[0][2] + vec->y * trans->matrix[1][2] +
  323.             vec->z * trans->matrix[2][2] + trans->translate.z;
  324.     *vec = tmp;
  325. }
  326.  
  327. /*
  328.  * 'c1x' is the X (0th) component of the first column, and so on.
  329.  */
  330. void
  331. ArbitraryMatrix(c1x, c2x, c3x, c1y, c2y, c3y, c1z, c2z, c3z, tx, ty, tz, trans)
  332. Float c1x, c1y, c1z, c2x, c2y, c2z, c3x, c3y, c3z, tx, ty, tz;
  333. RSMatrix *trans;
  334. {
  335.     trans->matrix[0][0] = c1x;
  336.     trans->matrix[1][0] = c1y;
  337.     trans->matrix[2][0] = c1z;
  338.  
  339.     trans->matrix[0][1] = c2x;
  340.     trans->matrix[1][1] = c2y;
  341.     trans->matrix[2][1] = c2z;
  342.  
  343.     trans->matrix[0][2] = c3x;
  344.     trans->matrix[1][2] = c3y;
  345.     trans->matrix[2][2] = c3z;
  346.  
  347.     trans->translate.x = tx;
  348.     trans->translate.y = ty;
  349.     trans->translate.z = tz;
  350. }
  351.  
  352. /*
  353.  * Apply transformation to a vector (translations have no effect).
  354.  */
  355. void
  356. VecTransform(vec, trans)
  357. Vector *vec;
  358. RSMatrix *trans;
  359. {
  360.     Vector tmp;
  361.  
  362.     tmp.x = vec->x*trans->matrix[0][0] +
  363.         vec->y*trans->matrix[1][0] + vec->z*trans->matrix[2][0];
  364.     tmp.y = vec->x*trans->matrix[0][1] +
  365.         vec->y*trans->matrix[1][1] + vec->z*trans->matrix[2][1];
  366.     tmp.z = vec->x*trans->matrix[0][2] +
  367.         vec->y*trans->matrix[1][2] + vec->z*trans->matrix[2][2];
  368.  
  369.     *vec = tmp;
  370. }
  371.  
  372. /*
  373.  * Transform normal -- multiply by the transpose of the given
  374.  * matrix (which is the inverse of the 'desired' transformation).
  375.  */
  376. void
  377. NormalTransform(norm, it)
  378. Vector *norm;
  379. RSMatrix *it;
  380. {
  381.     Vector onorm;
  382.  
  383.     onorm = *norm;
  384.  
  385.     norm->x = onorm.x*it->matrix[0][0] + onorm.y*it->matrix[0][1] +
  386.                 onorm.z*it->matrix[0][2];
  387.     norm->y = onorm.x*it->matrix[1][0] + onorm.y*it->matrix[1][1] +
  388.                 onorm.z*it->matrix[1][2];
  389.     norm->z = onorm.x*it->matrix[2][0] + onorm.y*it->matrix[2][1] +
  390.                 onorm.z*it->matrix[2][2];
  391.     (void)VecNormalize(norm);
  392. }
  393.  
  394. /*
  395.  * Transform "ray" by transforming the origin point and direction vector.
  396.  */
  397. Float
  398. RayTransform(ray, trans)
  399. Ray *ray;
  400. RSMatrix *trans;
  401. {
  402.     PointTransform(&ray->pos, trans);
  403.     VecTransform(&ray->dir, trans);
  404.     return VecNormalize(&ray->dir);
  405. }
  406.  
  407. void
  408. TransPropagate(trans)
  409. Trans *trans;
  410. {
  411.     (*trans->methods->propagate)(trans->tr, &trans->trans, &trans->itrans);
  412. }
  413.  
  414. void
  415. TransResolveAssoc(trans)
  416. Trans *trans;
  417. {
  418.     Trans *curtrans;
  419.     ExprAssoc *curassoc;
  420.  
  421.     for (curtrans = trans; curtrans; curtrans = curtrans->next) {
  422.         for (curassoc = curtrans->assoc; curassoc; curassoc = curassoc->next) {
  423.             *curassoc->lhs = ExprEval(curassoc->expr);
  424.         }
  425.         if (curtrans->assoc)
  426.             TransPropagate(curtrans);
  427.     }
  428. }
  429.  
  430. void
  431. TransComposeList(list, result)
  432. Trans *list, *result;
  433. {
  434.     TransCopy(list, result);
  435.     for (list = list->next; list; list = list->next)
  436.         TransCompose(list, result, result);
  437. }
  438.